package com.twoscreen;

import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.annotations.NotPersistent;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

@PersistenceCapable
public class QuestionMulti extends Question {
	@NotPersistent
	private static PersistenceManager pm = PMF.get().getPersistenceManager();
	
	@NotPersistent
	private static final Logger log = Logger.getLogger("com.twoscreen.QuestionMulti.java");
	
	@NotPersistent
	private static final String questionPropertyName = "question";
	
	@NotPersistent
	private static final String optionAPropertyName = "optionA";
	
	@NotPersistent
	private static final String optionBPropertyName = "optionB";
	
	@NotPersistent
	private static final String optionCPropertyName = "optionC";
	
	@NotPersistent
	private static final String optionDPropertyName = "optionD";
	
	@Persistent
	private String question;
	
	@Persistent
	private String optionA;
	
	@Persistent
	private String optionB;
	
	@Persistent
	private String optionC;
	
	@Persistent
	private String optionD;
	
	@Persistent
	private String correct;
	
	public QuestionMulti(String q, String a, String b, String c, String d, String correct, String videoId,
			int points) {
		this.question = q;
		this.optionA = a;
		this.optionB = b;
		this.optionC = c;
		this.optionD = d;
		this.correct = correct;
		super.setVideoId(videoId);
		super.setTimeStamp(new Date());
		super.setPoints(points);
		pm.makePersistent(this);
		Key key = super.getKey();
		log.info("Multi question added added: id: " + key.getId() +
				" question: " + question +
				" optionA: " + optionA +
				" optionB: " + optionB +
				" optionC: " + optionC +
				" optionD: " + optionD +
				" correct: " + correct +
				" videoId: " + videoId);
	}
	
	public Key getKey() {
		return super.getKey();
	}
	
	public String getVideoId() {
		return super.getVideoId();
	}
	
	public Integer getPoints() {
		return super.getPoints();
	}

	public String getQuestion() {
		return question;
	}

	public String getOptionA() {
		return optionA;
	}

	public String getOptionB() {
		return optionB;
	}

	public String getOptionC() {
		return optionC;
	}

	public String getOptionD() {
		return optionD;
	}

	public String getCorrect() {
		return correct;
	}

	public static String getQuestionpropertyname() {
		return questionPropertyName;
	}

	public static String getOptionApropertyname() {
		return optionAPropertyName;
	}

	public static String getOptionBpropertyname() {
		return optionBPropertyName;
	}

	public static String getOptionCpropertyname() {
		return optionCPropertyName;
	}

	public static String getOptionDpropertyname() {
		return optionDPropertyName;
	}
	
	/**
	 * Returns an array of objects that match the passed video ID
	 * @param videoId The video ID to search for
	 * @return A List of QuestionMulti objects
	 */
	@SuppressWarnings("unchecked")
	public static List<QuestionMulti> getByVideoId(String videoId) {
		log.info("Getting for video: " + videoId);
		List<QuestionMulti> rtn = null;
		Query q = pm.newQuery(QuestionMulti.class);
		q.setFilter(Question.getVideoIdPropertyName() + " == videoIdParam");
		q.declareParameters("String videoIdParam");
		
		try {
			log.info("Running query");
			rtn = (List<QuestionMulti>) q.execute(videoId);
		} finally {
			q.closeAll();
		}
		
		log.info("Returning list with " + rtn.size() + " results");
		return rtn;
	}
	
	/**
	 * Returns a JSON object containing a correct answer as the value to
	 * a question ID as the key
	 * @param videoId The video ID to search for answers to
	 * @return A JSON object
	 */
	public static String getCorrectAnswersByVideoIdJSON(String videoId) {
		log.info("Getting correct answers for video: " + videoId);
		StringBuilder sb = new StringBuilder();
		List<QuestionMulti> results = getByVideoId(videoId);
		sb.append('{');
		for (QuestionMulti result : results) {
			long questionId = result.getKey().getId();
			String correctAnswer = result.getCorrect();
			sb.append("\"" + questionId + "\": \"" + correctAnswer + "\",");
		}
		log.info("Character to be deleted: " + sb.charAt((sb.length()-1)));
		sb.deleteCharAt((sb.length()-1));
		if (sb.length() > 1) {
			sb.append('}');
		}
		String jsonReply = sb.toString();
		log.info("returning string: " + jsonReply);
		return jsonReply;
	}
	
	/**
	 * Get the correct answer for the given question ID
	 * @param questionId The question ID to search for
	 * @return A String containing the correct answer
	 */
	public static String getCorrectAnswer(long questionId) {
		String answer = null;
		Key key = KeyFactory.createKey(QuestionMulti.class.getSimpleName(), questionId);
		log.info("Attempting to find the question in the datastore to get the answer");
		try {
			answer = pm.getObjectById(QuestionMulti.class, key).getCorrect();
			log.info("Found answer: " + answer);
		} catch (NullPointerException e) {
			log.info("Answer not found for question: " + questionId + "\nTest failed " + e);
		} catch (JDOObjectNotFoundException e) {
			log.info("Answer not found for question: " + questionId + "\nTest failed " + e);
		}
		
		return answer;
	}
	
	/**
	 * Returns a QuestionMulti object searched by the question ID
	 * the question ID is unique to each QuestionMulti object
	 * @param questionId The question ID to search for
	 * @return A QuestionMulti object
	 */
	public static QuestionMulti getQMObject(long questionId) {
		Key key = KeyFactory.createKey(QuestionMulti.class.getSimpleName(), questionId);
		QuestionMulti qm = pm.getObjectById(QuestionMulti.class, key);
		return qm;
	}
	
	public static JSONArray getPointsJSON(String videoId) {
		JSONArray json = new JSONArray();
		
		//Get the array of QuestionMulti objects for the video ID
		List<QuestionMulti> questions = getByVideoId(videoId);
		
		//Loop though adding the question ID and points to the JSON object
		for (QuestionMulti question : questions) {
			long qId = question.getKey().getId();
			int points = question.getPoints();
			try {
				JSONObject obj = new JSONObject();
				obj.put("question", qId);
				obj.put("points", points);
				json.put(obj);
			} catch (JSONException e) {
				log.warning("Error with JSON");
				e.printStackTrace();
			}
		}
		
		return json;
	}

}
